home *** CD-ROM | disk | FTP | other *** search
- /************************************ intersect.c ******************/
- #include "sdi.h"
-
- /*
- * Copyright 1987 by Mark Weiser.
- * Permission to reproduce and use in any manner whatsoever on Suns is granted
- * so long as this copyright and other identifying marks of authorship
- * in the code and the game remain intact and visible. Use of this code
- * in other products is reserved to me--I'm working on Mac and IBM versions.
- */
-
- /*
- * The code to intersect blasts, missiles, and lasers is in here,
- * as well as some blast-specific code.
- */
-
- #define LINE_GRAIN 20
-
- /* each 'line' is the head of a linked list of current blasts */
- static struct blast *lines_launch[MAX_LINES/LINE_GRAIN + 1], *lines_city[MAX_LINES/LINE_GRAIN + 1];
- static struct blast **init_line_from_bid(), **init_line_from_mid();
-
- /*
- * Clear out data structures which keep track of blasts.
- */
- init_intersect()
- {
- int i;
- for (i=0; i<(MAX_LINES/LINE_GRAIN +1); i++) {
- lines_launch[i] = NULL;
- lines_city[i] = NULL;
- }
- }
-
- /*
- * Register a blast for later display. After this call the blast will
- * automatically be incremented and decremented in size, and will be checked
- * for intersection with missiles.
- */
- add_blast(bid)
- register struct blast *bid;
- {
- /* for now don't sort, just stick at the head */
- register int pos = bid->orig_y / LINE_GRAIN;
- struct blast **lines;
- if (pos < 0 || pos >= MAX_LINES/LINE_GRAIN + 1) {
- return;
- }
- lines = init_line_from_bid(bid);
- bid->next = lines[pos];
- lines[pos] = bid;
- blast_count++;
- }
-
- /*
- * Remove a blast from the display list. The blast will no longer
- * intersect missiles, change in size, or be displayed. The blast must
- * have already been cleared from the display elsewhere. The storage
- * is not freed here, in case the blast is statically allocated.
- */
- remove_blast(bid)
- register struct blast *bid;
- {
- struct blast **lines = init_line_from_bid(bid);
- register struct blast *ptr = lines[bid->orig_y / LINE_GRAIN];
- if (ptr == bid) {
- /* head is special case */
- lines[bid->orig_y / LINE_GRAIN] = bid->next;
- } else {
- while ( ptr != NULL && ptr->next != bid )
- ptr = ptr->next;
- if (ptr != NULL)
- ptr->next = bid->next;
- }
- blast_count--;
- }
-
- /*
- * See if the missile 'mid' has run into any blasts.
- */
- intersect(mid)
- struct missile *mid;
- {
- int start = max((mid->y - (MAX_CIRCLE >> 1) - 1) / LINE_GRAIN, 0);
- int end = min((mid->y + (MAX_CIRCLE >> 1) + 1) / LINE_GRAIN, max_y);
- register int i;
- register struct blast *ptr;
- struct blast **lines = init_line_from_mid(mid);
- for (i=start; i <= end; i++) {
- ptr = lines[i];
- while (ptr != NULL) {
- if (single_intersect(ptr, mid))
- return TRUE;
- ptr = ptr->next;
- }
- }
- return FALSE;
- }
-
- /*
- * See if the missile 'mid' is passing through blast 'bid'. This routine
- * is also used for laser initialization, with a fake 'bid' to simulate
- * the laser range. For purposes of computing intersection, the circular
- * blast is considerd to be a rectangle with the same center and approximately
- * the same area. An intersection has occured if the missile passed
- * through the blast between its last update and now, even if both endpoints
- * are outside the blast.
- */
- single_intersect(bid,mid)
- struct missile *mid;
- struct blast *bid;
- {
- int x0 = mid->old_x, y0 = mid->old_y, x1 = mid->x, y1 = mid->y;
- return rect_clipvector(&bid->r, &x0, &y0, &x1, &y1);
- }
-
- /*
- * Procedure 'func' is called for every blast on the display lists.
- */
- doto_blasts(func)
- int (*func)();
- {
- int i;
- struct blast *bid, *next;
- struct blast **lines;
- lines = lines_launch;
- for (i=0; i< (MAX_LINES/LINE_GRAIN + 1); i++) {
- bid = lines[i];
- while (bid != NULL) {
- next = bid->next; /* in case func destroys it */
- (*func)(bid);
- bid = next;
- }
- }
- lines = lines_city;
- for (i=0; i<(MAX_LINES/LINE_GRAIN + 1); i++) {
- bid = lines[i];
- while (bid != NULL) {
- next = bid->next; /* in case func destroys it */
- (*func)(bid);
- bid = next;
- }
- }
- }
-
- /*
- * Given a blast, return the proper display on which it will be found.
- */
- static struct blast **
- init_line_from_bid(bid)
- struct blast *bid;
- {
- if (bid->pw == launchpw) {
- return lines_launch;
- } else {
- return lines_city;
- }
- }
-
- /*
- * Given a missile, return the proper display list on which intersecting
- * blasts will be found.
- */
- static struct blast **
- init_line_from_mid(mid)
- struct missile *mid;
- {
- if (mid->pw == launchpw) {
- return lines_launch;
- } else {
- return lines_city;
- }
- }
-
- /*
- * Remove all blasts from the display lists and free their storage.
- * Nothing is done here about getting them off the display.
- */
- static struct blast **line_list[] = {lines_launch, lines_city};
- free_all_blasts()
- {
- int i, l;
- struct blast *bid, *nextbid, **lines;
- for (l=0; l < 2; l++) {
- lines = line_list[l];
- for (i=0; i<(MAX_LINES/LINE_GRAIN + 1); i++) {
- bid = lines[i];
- lines[i] = NULL;
- while (bid != NULL) {
- nextbid = bid->next;
- free(bid);
- bid = nextbid;
- }
- }
- }
- blast_count = 0;
- }
-
- /*
- This is the old style, now commented out. It would let a fast
- moving missile pass right through, but did consider blasts to
- be real circles.
-
- single_intersect(bid, mid)
- struct blast *bid;
- struct missile *mid;
- {
- register short offx = B_WIDTH(bid)/2;
- register short x = bid->x - mid->x;
- register short y = bid->y - mid->y;
- return (x*x + y*y) < (offx*offx);
- }
- */
-
-